package net.mikoo.seals.api.controller;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.alibaba.fastjson.JSONObject;

import net.glxn.qrgen.QRCode;
import net.mikoo.seals.api.model.BaseResponse;
import net.mikoo.seals.api.model.ResultType;
import net.mikoo.seals.api.model.use.ActDetailRequest;
import net.mikoo.seals.api.model.use.ActDetailResponse;
import net.mikoo.seals.api.model.use.CensorRequest;
import net.mikoo.seals.api.model.use.CheckScanRequest;
import net.mikoo.seals.api.model.use.CheckScanResponse;
import net.mikoo.seals.api.model.use.GetAcodeRequest;
import net.mikoo.seals.api.model.use.GetScanStatusRequest;
import net.mikoo.seals.api.model.use.GetScanStatusResponse;
import net.mikoo.seals.api.model.use.GetWaitUseDetailRequest;
import net.mikoo.seals.api.model.use.GetWaitUseDetailResponse;
import net.mikoo.seals.api.model.use.GetWaitUseListRequest;
import net.mikoo.seals.api.model.use.GetWaitUseListResponse;
import net.mikoo.seals.api.model.use.GiveBackRequest;
import net.mikoo.seals.api.model.use.RollBackRequest;
import net.mikoo.seals.api.model.use.UploadUseImgRequest;
import net.mikoo.seals.api.model.use.UseActsRequest;
import net.mikoo.seals.api.model.use.UseActsResponse;
import net.mikoo.seals.api.model.use.UseDetailRequest;
import net.mikoo.seals.api.model.use.UseDetailResponse;
import net.mikoo.seals.api.model.use.UseRecordDetailRequest;
import net.mikoo.seals.api.model.use.UseRecordDetailResponse;
import net.mikoo.seals.api.model.use.UseRecordRequest;
import net.mikoo.seals.api.model.use.UseRecordResponse;
import net.mikoo.seals.api.model.use.UseRequest;
import net.mikoo.seals.api.model.use.UseResponse;
import net.mikoo.seals.api.utility.ApiConstants;
import net.mikoo.seals.api.utility.PartyUtility;
import net.mikoo.seals.biz.common.LocationUtility;
import net.mikoo.seals.biz.service.ApplyServices;
import net.mikoo.seals.biz.service.DevicesActService;
import net.mikoo.seals.biz.service.DevicesServices;
import net.mikoo.seals.biz.service.DevicesTakeService;
import net.mikoo.seals.biz.service.DevicesUsedServices;
import net.mikoo.seals.biz.service.SealServices;
import net.mikoo.seals.common.enums.ApplyTypeEnum;
import net.mikoo.seals.common.enums.CensorStatusEnum;
import net.mikoo.seals.common.enums.TakeStatusEnum;
import net.mikoo.seals.common.exception.ParametersException;
import net.mikoo.seals.common.model.PageModel;
import net.mikoo.seals.model.Apply;
import net.mikoo.seals.model.Devices;
import net.mikoo.seals.model.DevicesAct;
import net.mikoo.seals.model.DevicesActQuery;
import net.mikoo.seals.model.DevicesTake;
import net.mikoo.seals.model.DevicesTakeQuery;
import net.mikoo.seals.model.DevicesUsed;
import net.mikoo.seals.model.DevicesUsedCert;
import net.mikoo.seals.model.DevicesUsedCertUpfile;
import net.mikoo.seals.model.DevicesUsedFail;
import net.mikoo.seals.model.DevicesUsedQuery;
import net.mikoo.seals.model.Party;
import net.mikoo.seals.model.Seal;
import net.mikoo.seals.utils.AESUtility;

@Controller
public class UseController {

	private static Logger logger = LoggerFactory.getLogger(UseController.class);
	
	@Autowired
	private DevicesTakeService devicesTakeService;
	
	@Autowired
	private DevicesActService devicesActService;
	
	@Autowired
	private DevicesServices devicesServices;
	
	@Autowired
	private DevicesUsedServices devicesUsedServices;
	
	@Autowired
	private ApplyServices applyServices;
	
	@Autowired
	private SealServices sealServices;
	
	@Autowired
	private StringRedisTemplate redisTemplate;
	
	@RequestMapping("/use/getWaitUseList")
	@ResponseBody
	public GetWaitUseListResponse getWaitUseList(GetWaitUseListRequest request, HttpServletRequest httpRequest) {
		GetWaitUseListResponse result = new GetWaitUseListResponse();
		try {
			ApplyTypeEnum applyType = ApplyTypeEnum.getByCode(request.getApplyType());
			if(applyType == null) {
				throw new ParametersException("applyType is null");
			}
			
			Long partyId = PartyUtility.getCurrentPartyId(httpRequest);
			Long companyId = PartyUtility.getCurrentPartyCompanyId(httpRequest);
			
			if(applyType == ApplyTypeEnum.TAKE_APPLY) {
				DevicesTakeQuery devicesTakeQuery = new DevicesTakeQuery();
				devicesTakeQuery.setPartyId(partyId);
				devicesTakeQuery.setInvalidStatus(TakeStatusEnum.RETURND.getCode());
				List<DevicesTake> takeList = devicesTakeService.getListByQuery(devicesTakeQuery);
				result = GetWaitUseListResponse.fromTake(takeList);
			}else {
				DevicesActQuery devicesActQuery = new DevicesActQuery();
				devicesActQuery.setPartyId(partyId);
				devicesActQuery.setCompanyId(companyId);
				devicesActQuery.setWaitUse(true);
				devicesActQuery.setDevicesId(request.getDevicesId());
				devicesActQuery.setSealId(request.getSealId());
				devicesActQuery.setApplyType(request.getApplyType());
				List<DevicesAct> actList = devicesActService.getListByQuery(devicesActQuery);
				result = GetWaitUseListResponse.fromAct(actList);
			}
			
			result.setResult(ResultType.SUCCESS.getValue());
		}catch(Exception e) {
			logger.error("", e);
			result.setResult(ResultType.ERROR.getValue());
		}
		return result;
	}
	
	@RequestMapping("/use/getWaitUseDetail")
	@ResponseBody
	public GetWaitUseDetailResponse getWaitUseDetail(GetWaitUseDetailRequest getWaitUseDetailRequest, HttpServletRequest request) {
		
		GetWaitUseDetailResponse result = new GetWaitUseDetailResponse();
		try {
			
			if(getWaitUseDetailRequest == null) {
				throw new ParametersException("getWaitUseDetailRequest");
			}
			
			if(getWaitUseDetailRequest.getId() == null) {
				throw new ParametersException("getWaitUseDetailRequest.getId");
			}
			
			ApplyTypeEnum applyType = ApplyTypeEnum.getByCode(getWaitUseDetailRequest.getType());
			if(applyType != ApplyTypeEnum.TAKE_APPLY && applyType != ApplyTypeEnum.USED_APPLY) {
				throw new ParametersException("applyType");
			}
			
			Party party = PartyUtility.getCurrentParty(request);
			if(party == null) {
				throw new IllegalStateException("need login");
			}
			if(applyType == ApplyTypeEnum.TAKE_APPLY) {
				DevicesTake devicesTake = devicesTakeService.getById(getWaitUseDetailRequest.getId());
				if(devicesTake == null) {
					throw new IllegalArgumentException("待出借的印章数据不存在");
				}
				
				Apply apply = applyServices.getById(devicesTake.getApplyId());
				if(apply != null) {
					apply.setUpfiles(applyServices.getApplyfiles(devicesTake.getApplyId()));
					devicesTake.setApply(apply);
				}
				
				if(devicesTake.getDevicesId() != null) {
					Devices devices = devicesServices.getInfoById(devicesTake.getDevicesId());
					devicesTake.setDevices(devices);
				}
				
				result = GetWaitUseDetailResponse.valueOf(devicesTake);
			}else {
				DevicesAct devicesAct = devicesActService.getInfoById(getWaitUseDetailRequest.getId());
				if(devicesAct == null) {
					throw new IllegalArgumentException("待使用的印章数据不存在");
				}
				
				Apply apply = applyServices.getById(devicesAct.getApplyId());
				if(apply != null) {
					apply.setUpfiles(applyServices.getApplyfiles(devicesAct.getApplyId()));
					devicesAct.setApply(apply);
				}

				if(devicesAct.getDevicesId() != null) {
					Devices devices = devicesServices.getInfoById(devicesAct.getDevicesId());
					devicesAct.setDevices(devices);
				}
				
				result = GetWaitUseDetailResponse.valueOf(devicesAct);
			}
			
			result.setResult(ResultType.SUCCESS.getValue());
		}catch(Exception e) {
			logger.error("", e);
			result.setResult(ResultType.ERROR.getValue());
		}
		return result;
		
	}
	
	@RequestMapping("/use/qrcode")
	public void qrcode(GetAcodeRequest getAcodeRequest, HttpServletRequest request, HttpServletResponse response) {
	    InputStream is = null;
	    OutputStream os = null;
	    try {
	    	
	    	if(getAcodeRequest == null) {
	    		throw new IllegalArgumentException("getAcodeRequest");
	    	}
	    	if(getAcodeRequest.getId() == null) {
	    		throw new IllegalArgumentException("getAcodeRequest.getId");
	    	}
	    	
	    	ApplyTypeEnum applyType = ApplyTypeEnum.getByCode(getAcodeRequest.getType());
	    	if(applyType == null) {
	    		throw new IllegalArgumentException("applyType");
	    	}
    	    String params = getParams(PartyUtility.getCurrentPartyId(request), getAcodeRequest.getId(), applyType);
    	    QRCode qrcode = QRCode.from(params);
    	    qrcode.withSize(500, 500);
            response.setHeader("Content-Type", "image/jpeg");
            ByteArrayOutputStream qrStream = qrcode.stream();
	        os = response.getOutputStream();
            os.write(qrStream.toByteArray());
	        os.flush();
        } catch (Exception e) {
        	logger.error("", e);
        }finally {
            if(is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                } 
            }
            if(os != null) {
               try {
                    os.close();
                } catch (IOException e) {
                    e.printStackTrace();
                } 
            }
        }
	}
	
	@RequestMapping("/use/useDetail")
	@ResponseBody
	public UseDetailResponse useDetail(UseDetailRequest useDetailRequest, HttpServletRequest request) {
		UseDetailResponse result = new UseDetailResponse();
		try {
			
			if(useDetailRequest == null) {
				throw new ParametersException("useDetailRequest");
			}
			
			if(useDetailRequest.getId() == null) {
				throw new ParametersException("useDetailRequest.id");
			}
			
			ApplyTypeEnum applyType = ApplyTypeEnum.getByCode(useDetailRequest.getType());
			if(applyType == ApplyTypeEnum.USED_APPLY || applyType == ApplyTypeEnum.TEST_APPLY || applyType == ApplyTypeEnum.URGENT_APPLY) {
				DevicesAct act = devicesActService.getInfoById(useDetailRequest.getId());
				if(act == null || 
						act.getTotalTimes() - act.getUseTimes() <= 0 ||
								(!CensorStatusEnum.WAIT.getCode().equals(act.getCensorStatus()) && !StringUtils.isBlank(act.getCensorStatus()))) {
					throw new ParametersException("");
				}
				
				result = UseDetailResponse.valueOf(act);
			}else {
				throw new IllegalArgumentException("无效使用类型");
			}
			result.setResult(ResultType.SUCCESS.getValue());
		}catch(Exception e) {
			logger.error("", e);
			result.setResult(ResultType.ERROR.getValue());
		}
		return result;
	}
	
	@RequestMapping("/use/use")
	@ResponseBody
	public UseResponse use(UseRequest useRequest, HttpServletRequest httpRequest) {
		
		UseResponse result = new UseResponse();
		try {
			
			if(useRequest == null) {
				throw new ParametersException("useRequest");
			}
			
			if(useRequest.getId() == null) {
				throw new ParametersException("useRequest.id");
			}
			
			if(useRequest.getPartyId() == null) {
				throw new ParametersException("useRequest.PartyId");
			}
			
			if(useRequest.getDevicesId() == null) {
				throw new ParametersException("useRequest.DevicesId");
			}
			
			if(StringUtils.isBlank(useRequest.getType())) {
				throw new ParametersException("useRequest.type");
			}
			
			ApplyTypeEnum applyType = ApplyTypeEnum.getByCode(useRequest.getType());
			
			
			if(applyType == ApplyTypeEnum.TAKE_APPLY) {
				
				DevicesTake take = new DevicesTake();
				take.setDevicesTakeId(useRequest.getId());
				take.setDevicesId(useRequest.getDevicesId());
				devicesServices.take(take, PartyUtility.getCurrentPartyId(httpRequest));
			}else if(applyType == ApplyTypeEnum.TEST_APPLY || 
					applyType == ApplyTypeEnum.USED_APPLY || 
					applyType == ApplyTypeEnum.URGENT_APPLY) {
				DevicesUsed devicesUsed = new DevicesUsed();
				devicesUsed.setDevicesActId(useRequest.getId());
				devicesUsed.setPartyId(useRequest.getPartyId());
				devicesUsed.setDevicesId(useRequest.getDevicesId());
				devicesUsed.setUsedIp(httpRequest.getRemoteAddr());
				devicesUsed.setCompanyId(PartyUtility.getCurrentPartyCompanyId(httpRequest));
				
				if(useRequest.getLongitude() != null && useRequest.getLatitude() != null) {
					String location = useRequest.getLongitude() + "," + useRequest.getLatitude();
					devicesUsed.setUsedGps(location);
					devicesUsed.setUsedAddr(LocationUtility.getGodeAddr(location));
				}
				devicesUsed.setOperatorPartyId(PartyUtility.getCurrentPartyId(httpRequest));
				devicesServices.used(devicesUsed);
				result.setUseId(devicesUsed.getDevicesUsedId());
			}else {
				throw new ParametersException("request type");
			}
			
			result.setResult(ResultType.SUCCESS.getValue());
		}catch(Exception e) {
			logger.error("", e);
			result.setResult(ResultType.ERROR.getValue());
		}
		return result;
	}
	
	@RequestMapping("/use/rollback")
	@ResponseBody
	public BaseResponse rollBack(RollBackRequest request, HttpServletRequest httpRequest) {
		BaseResponse result = new BaseResponse();
		try {
			
			if(request == null) {
				throw new IllegalArgumentException("request");
			}
			
			if(request.getActId() == null) {
				throw new IllegalArgumentException("request.actId");
			}
			
			DevicesUsedFail fail = new DevicesUsedFail();
			fail.setOperactorPartyId(PartyUtility.getCurrentPartyId(httpRequest));
			fail.setCause(request.getCause());
			fail.setDevicesActId(request.getActId());
			if(request.getLongitude() != null && request.getLatitude() != null) {
				String location = request.getLongitude() + "," + request.getLatitude();
				fail.setUsedGps(location);
				fail.setUsedAddr(LocationUtility.getGodeAddr(location));
			}
			
			devicesServices.rollBackUse(fail, request.getTimes());
			result.setResult(ResultType.SUCCESS.getValue());
		}catch(Exception e) {
			logger.error("", e);
			result.setResult(ResultType.ERROR.getValue());
		}
		return result;
	}
	
	@RequestMapping("/use/uploadUseImg")
	@ResponseBody
	public BaseResponse updateLoadImg(UploadUseImgRequest uploadUseImgRequest, HttpServletRequest httpRequest) {
		BaseResponse result = new BaseResponse();
		try {
			
			if(uploadUseImgRequest == null) {
				throw new ParametersException("uploadUseImgRequest");
			}
			
			if(uploadUseImgRequest.getActId() == null) {
				throw new ParametersException("uploadUseImgRequest.ActId");
			}
			
			if(StringUtils.isBlank(uploadUseImgRequest.getFileIds())) {
				throw new ParametersException("uploadUseImgRequest.FileIds");
			}
			
			DevicesUsedCert cer = new DevicesUsedCert();
			cer.setDevicesActId(uploadUseImgRequest.getActId());
			cer.setCompanyId(PartyUtility.getCurrentPartyCompanyId(httpRequest));
			List<DevicesUsedCertUpfile> upfiles = new ArrayList<DevicesUsedCertUpfile>();
			for(String fileId : uploadUseImgRequest.getFileIds().split(",")) {
				DevicesUsedCertUpfile upfile = new DevicesUsedCertUpfile();
				upfile.setUpfileId(Long.valueOf(fileId));
				upfiles.add(upfile);
			}
			cer.setDevicesUsedCertUpfiles(upfiles);
			devicesServices.setUsedImg(cer);
			result.setResult(ResultType.SUCCESS.getValue());
		}catch(Exception e) {
			logger.error("", e);
			result.setResult(ResultType.ERROR.getValue());
		}
		return result;
	}
	
	@RequestMapping("/use/getScanStatus")
	@ResponseBody
	public GetScanStatusResponse getScanStatus(GetScanStatusRequest request) {
		GetScanStatusResponse result = new GetScanStatusResponse();
		try {
			if(request.getUseId() == null) {
				throw new ParametersException("useId is null");
			}
			
			String key = String.format(ApiConstants.USE_KEY_FORMAT, request.getUseId());
			ValueOperations<String, String> vo = redisTemplate.opsForValue();
			
			String res = vo.get(key);
			if(StringUtils.isBlank(res)) {
				throw new ParametersException("useId error");
			}
			
			result.setKey(key);
			result.setValue(res);
			
			JSONObject json = JSONObject.parseObject(res);
			if(!json.getBoolean("status")) {
				throw new Exception("no scan");
			}
			vo.set(key, res, 1, TimeUnit.MILLISECONDS);
			result.setResult(ResultType.SUCCESS.getValue());
		}catch(Exception e) {
			logger.error("", e);
			result.setResult(ResultType.ERROR.getValue());
		}
		return result;
	}
	
	@RequestMapping("/use/checkScan")
	@ResponseBody
	public CheckScanResponse checkScan(CheckScanRequest request, HttpServletRequest httpRequest) {
		CheckScanResponse result = new CheckScanResponse();
		try {
			
			if(StringUtils.isBlank(request.getKey())) {
				throw new ParametersException("无效二维码");
			}
			
			if(StringUtils.isBlank(request.getValue())) {
				throw new ParametersException("无效二维码");
			}
			
			ValueOperations<String, String> vo = redisTemplate.opsForValue();
			
			String res = vo.get(request.getKey());
			if(StringUtils.isBlank(res)) {
				throw new ParametersException("无效二维码");
			}
			
			JSONObject json = JSONObject.parseObject(res);
			if(json.getBoolean("status")) {
				throw new ParametersException("无效二维码");
			}
			
			if(!request.getValue().equals(json.getString("value"))) {
				throw new ParametersException("二维码内容被篡改了");
			}
			
			String oriText = new String(AESUtility.decrypt(AESUtility.parseHexStr2Byte(json.getString("value")), ApiConstants.AES_KEY));
			
			JSONObject useJson = JSONObject.parseObject(oriText);
			
			if(useJson == null) {
				throw new ParametersException("无效二维码");
			}
			
			
			Long sealId = useJson.getLong("sealId");
			if(sealId == null) {
				throw new ParametersException("无效二维码");
			}
			
			Seal seal = sealServices.getInfoById(sealId);
			if(seal == null) {
				throw new ParametersException("无效二维码");
			}
			
			DevicesTakeQuery devicesTakeQuery = new DevicesTakeQuery();
			devicesTakeQuery.setDevicesId(useJson.getLong("devicesId"));
			devicesTakeQuery.setTakeStatus(TakeStatusEnum.WAIT_RETURN.getCode());
			devicesTakeQuery.setStartDate(new Date());
			DevicesTake devicesTake = devicesTakeService.getInfoByQuery(devicesTakeQuery);
			
			Long partyId = PartyUtility.getCurrentPartyId(httpRequest);
			
			if(partyId == null) {
				throw new ParametersException("用户未登陆");
			}
			
			if(!(
					// 管理员
					partyId.equals(seal.getPartyId()) || 
					// 临时管理员
					(
							partyId.equals(seal.getInterimPartyId()) && 
							seal.getInterimExpiredDate() != null && 
							seal.getInterimExpiredDate().getTime() > System.currentTimeMillis()
					) || 
					// 外带
					(devicesTake != null && partyId.equals(devicesTake.getPartyId()))
					)) {
				throw new ParametersException("您无权进行此操作");
			}
			
			result.setSealId(useJson.getLong("sealId"));
			result.setType(useJson.getString("type"));
			result.setUseId(useJson.getLong("useId"));
			result.setDevicesId(useJson.getLong("devicesId"));
			
			json.put("status", true);
			vo.set(request.getKey(), json.toJSONString());
			
			result.setResult(ResultType.SUCCESS.getValue());
		}catch(ParametersException pe) {
			logger.error("", pe);
			result.setResult(ResultType.ERROR.getValue());
			result.setErrorMsg(pe.getMessage());
		}catch(Exception e) {
			logger.error("", e);
			result.setResult(ResultType.ERROR.getValue());
		}
		return result;
	}
	
	@RequestMapping("/use/acts")
	@ResponseBody
	public UseActsResponse acts(UseActsRequest request, HttpServletRequest httpRequest) {
		
		UseActsResponse result = new UseActsResponse();
		try {
			if(request == null) {
				throw new ParametersException("request");
			}
			
			if(request.getPageNo() == null || request.getPageNo() < 0) {
				request.setPageNo(1);
			}
			
			if(request.getPageSize() == null || request.getPageSize() < 0) {
				request.setPageSize(10);
			}
			
			DevicesActQuery devicesActQuery = new DevicesActQuery();
			SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
			if(StringUtils.isNotBlank(request.getStartTime())) {
				devicesActQuery.setStartTime(sdf.parse(request.getStartTime() + " 00:00:00"));
			}
			
			if(StringUtils.isNotBlank(request.getEndTime())) {
				devicesActQuery.setEndTime(sdf.parse(request.getEndTime() + " 23:59:59"));
			}
			
			if(request.getDevicesId() != null) {
				devicesActQuery.setDevicesId(request.getDevicesId());
			}

			if(!"all".equals(request.getType())) {
				devicesActQuery.setPartyId(PartyUtility.getCurrentPartyId(httpRequest));
			}
			
			if(StringUtils.isNotBlank(request.getApplyType())) {
				ApplyTypeEnum applyType = ApplyTypeEnum.getByCode(request.getApplyType());
				if(applyType != null) {
					devicesActQuery.setApplyType(applyType.getCode());
				}
			}
			
			devicesActQuery.setOffset((request.getPageNo() - 1)*request.getPageSize());
			devicesActQuery.setPageSize(request.getPageSize());
			devicesActQuery.setOrderColumn("da.last_updated_stamp");
			devicesActQuery.setOrderType("desc");
			devicesActQuery.setCompanyId(PartyUtility.getCurrentPartyCompanyId(httpRequest));
			devicesActQuery.setIsUsed(true);
			PageModel<DevicesAct> pm = devicesActService.getActPageByQuery(devicesActQuery);
			
			result = UseActsResponse.valueOf(pm);
			result.setResult(ResultType.SUCCESS.getValue());
		}catch(Exception e) {
			logger.error("", e);
			result.setResult(ResultType.ERROR.getValue());
		}
		return result;
		
	}
	
	@RequestMapping("/use/actDetail")
	@ResponseBody
	public ActDetailResponse actDetail(ActDetailRequest request) {
		ActDetailResponse result = new ActDetailResponse();
		try {
			if(request == null) {
				throw new IllegalArgumentException("request");
			}

			if(request.getActId() == null) {
				throw new IllegalArgumentException("request.getActId");
			}
			
			DevicesAct actModel = devicesActService.getInfoById(request.getActId());
			
			if(actModel != null) {
				result = ActDetailResponse.valueOf(actModel);
			}
			result.setResult(ResultType.SUCCESS.getValue());
		}catch(Exception e) {
			logger.error("", e);
			result.setResult(ResultType.ERROR.getValue());
		}
		return result;
	}
	
	@RequestMapping("/use/record")
	@ResponseBody
	public UseRecordResponse useRecord(UseRecordRequest useRecordRequest, HttpServletRequest httpRequest) {
		UseRecordResponse result = new UseRecordResponse();
		try {
			if(useRecordRequest == null) {
				throw new ParametersException("useRecordRequest");
			}
			
			if(useRecordRequest.getPageNo() == null || useRecordRequest.getPageNo() < 0) {
				useRecordRequest.setPageNo(1);
			}
			
			if(useRecordRequest.getPageSize() == null || useRecordRequest.getPageSize() < 0) {
				useRecordRequest.setPageSize(10);
			}
			
			DevicesUsedQuery devicesUsedQuery = new DevicesUsedQuery();
			if(useRecordRequest.getDevicesId() != null) {
				devicesUsedQuery.setDevicesId(useRecordRequest.getDevicesId());
			}else {
				devicesUsedQuery.setPartyId(PartyUtility.getCurrentPartyId(httpRequest));
			}
			SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
			if(StringUtils.isNotBlank(useRecordRequest.getStartTime())) {
				devicesUsedQuery.setStartTime(sdf.parse(useRecordRequest.getStartTime() + " 00:00:00"));
			}
			
			if(StringUtils.isNotBlank(useRecordRequest.getEndTime())) {
				devicesUsedQuery.setEndTime(sdf.parse(useRecordRequest.getEndTime() + " 23:59:59"));
			}
			devicesUsedQuery.setDevicesActId(useRecordRequest.getActId());
			devicesUsedQuery.setOffset((useRecordRequest.getPageNo() - 1)*useRecordRequest.getPageSize());
			devicesUsedQuery.setPageSize(useRecordRequest.getPageSize());
			devicesUsedQuery.setApplyType(useRecordRequest.getApplyType());
			devicesUsedQuery.setOrderColumn("used_time");
			devicesUsedQuery.setOrderType("desc");
			devicesUsedQuery.setCompanyId(PartyUtility.getCurrentPartyCompanyId(httpRequest));
			PageModel<DevicesUsed> pm = devicesUsedServices.getPageByQuery(devicesUsedQuery);
			
			result = UseRecordResponse.valueOf(pm);
			result.setResult(ResultType.SUCCESS.getValue());
		}catch(Exception e) {
			logger.error("", e);
			result.setResult(ResultType.ERROR.getValue());
		}
		return result;
	}
	
	@RequestMapping("/use/recordDetail")
	@ResponseBody
	public UseRecordDetailResponse recordDetail(UseRecordDetailRequest request, HttpServletRequest httpRequest) {
		UseRecordDetailResponse result = new UseRecordDetailResponse();
		try {
			
			if(request == null) {
				throw new ParametersException("request");
			}
			
			if(request.getId() == null) {
				throw new ParametersException("id");
			}
			
			DevicesUsed devicesUsed = devicesUsedServices.getInfoById(request.getId());
			
			result = UseRecordDetailResponse.valueOf(devicesUsed);
			result.setResult(ResultType.SUCCESS.getValue());
		}catch(Exception e) {
			logger.error("", e);
			result.setResult(ResultType.ERROR.getValue());
		}
		return result;
	}
	
	@RequestMapping("/use/censor")
	@ResponseBody
	public BaseResponse censor(CensorRequest request, HttpServletRequest httpRequest) {
		
		BaseResponse result = new BaseResponse();
		try {
			
			if(request == null) {
				throw new ParametersException("request");
			}
			
			if(request.getActId() == null) {
				throw new ParametersException("actId");
			}
			
			DevicesAct act = new DevicesAct();
			act.setDevicesActId(request.getActId());
			act.setCensorPartyId(PartyUtility.getCurrentPartyId(httpRequest));
			act.setCompanyId(PartyUtility.getCurrentPartyCompanyId(httpRequest));
			devicesActService.censor(act);
			result.setResult(ResultType.SUCCESS.getValue());
		}catch(Exception e) {
			logger.error("", e);
			result.setResult(ResultType.ERROR.getValue());
		}
		return result;
		
	}

	@RequestMapping("/use/giveBack")
	@ResponseBody
	public BaseResponse giveBack(GiveBackRequest request, HttpServletRequest httpRequest) {
		BaseResponse result = new BaseResponse();
		try {
			
			if(request == null) {
				throw new ParametersException("request");
			}
			
			if(request.getTakeId() == null) {
				throw new ParametersException("TakeId");
			}
			
			if(request.getDevicesId() == null) {
				throw new ParametersException("DevicesId");
			}
			
			DevicesTake take = new DevicesTake();
			take.setDevicesTakeId(request.getTakeId());
			take.setDevicesId(request.getDevicesId());
			take.setCompanyId(PartyUtility.getCurrentPartyCompanyId(httpRequest));
			devicesTakeService.returns(take);
			result.setResult(ResultType.SUCCESS.getValue());
		}catch(Exception e) {
			logger.error("", e);
			result.setResult(ResultType.ERROR.getValue());
		}
		return result;
	}
	
	private String getParams(Long partyId, Long id, ApplyTypeEnum type) {
		assert partyId != null;
		assert id != null;
		assert type != null;
		JSONObject json = new JSONObject();
		
		if(type == ApplyTypeEnum.USED_APPLY) {
			DevicesAct devicesAct = devicesActService.getInfoById(id);
			if(devicesAct == null || devicesAct.getSealId() == null || !partyId.equals(devicesAct.getPartyId())) {
				throw new IllegalArgumentException("待使用记录数据错误");
			}
			
			json.put("useId", id);
			json.put("type", type.getCode());
			json.put("sealId", devicesAct.getSeal().getSealId());
			json.put("devicesId", devicesAct.getDevicesId());
		}else if(type == ApplyTypeEnum.TAKE_APPLY){
			DevicesTake devicesTake = devicesTakeService.getById(id);
			if(devicesTake == null || devicesTake.getSealId() == null || !partyId.equals(devicesTake.getPartyId())) {
				throw new IllegalArgumentException("待使用记录数据错误");
			}
			
			json.put("useId", id);
			json.put("type", type.getCode());
			json.put("sealId", devicesTake.getSealId());
			json.put("devicesId", devicesTake.getDevicesId());
		}else {
			throw new ParametersException("请求使用类型错误");
		}
		
		String key = String.format(ApiConstants.USE_KEY_FORMAT, json.getLong("useId"));
		ValueOperations<String, String> vo = redisTemplate.opsForValue();
		
		String cryptograph = AESUtility.parseByte2HexStr(AESUtility.encrypt(json.toJSONString(), ApiConstants.AES_KEY));
		JSONObject result = new JSONObject();
		result.put("key", key);
		result.put("value", cryptograph);
		result.put("status", false);
		
		vo.set(key, result.toJSONString());
		return result.toJSONString();
	}
}
